package com.cherrish.demo.thread;

import java.util.concurrent.CountDownLatch;

/**
 * @author cherrish
 * @time 2019-02-27 13:53
 * @name TestCountDownLatch
 * @desc:
 */
public class TestCountDownLatch {
    public long timeTasks(int nThreads, final Runnable task) throws InterruptedException {
        /**
         *一个启动信号，在 driver 为继续执行 worker 做好准备之前，它会阻止所有的 worker 继续执行。
         */
        final CountDownLatch startSignal = new CountDownLatch(1);
        /**
         * 一个完成信号，它允许 driver 在完成所有 worker 之前一直等待。
          */
        final CountDownLatch doneSignal = new CountDownLatch(nThreads);

        for (int i = 0; i < nThreads; i++) {
            Thread t = new Thread() {
                @Override
                public void run() {
                    try {
                        startSignal.await();/** 阻塞于此，一直到startSignal计数为0，再往下执行 */
                        try {
                            task.run();
                        } finally {
                            doneSignal.countDown();/** doneSignal 计数减一，直到最后一个线程结束 */
                        }
                    } catch (InterruptedException ignored) {
                    }
                }
            };
            t.start();
        }

        long start = System.currentTimeMillis();
        startSignal.countDown();/** doneSignal 计数减一，为0，所有task开始并发执行run */
        doneSignal.await();/** 阻塞于此，一直到doneSignal计数为0，再往下执行 */
        long end = System.currentTimeMillis();
        return end - start;

    }

    public static void main(String[] args) throws InterruptedException {

        final Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " end");
            }
        };
        long time = new TestCountDownLatch().timeTasks(10, task);
        System.out.println("耗时：" + time + "ms");

    }
}
